/**
 *
 * The MIT License
 *
 * Copyright (c) 2008 Board of Trustees, Leland Stanford Jr. University. All rights reserved.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:

 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.

 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package org.macdadi.core.server;

import javax.servlet.ServletException;
import javax.servlet.UnavailableException;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.PrintWriter;
import java.sql.*;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * @author Ben Suter <ben.suter@gmail.com>
 *
 * This servlet responds to HTTP GET requests by looking up the project
 * whose url_path attribute matches the remaining request URL path.
 * If a matching project is found, it generates an HTML host page containing
 * the MACDADI single-project application view. If not project matches,
 * a 404 not-found error is returned.
 */
public class ProjectServlet extends HttpServlet
{
    protected transient Connection db;
    protected final String dbPropertiesFile = "database.properties";
    protected final String dbPropertiesDriverClass = "driverclass";
    protected final String dbPropertiesConnectionString = "connectionstring-read";

    protected final String configPropertiesFile = "projectservlet.properties";
    protected final String configPropertiesGoogleAnalyticsCode = "google-analytics-code";
    protected final String configPropertiesUrlPathParam = "url-path-param";

    protected String googleAnalyticsCode;
    protected String urlPathParam;

    public void init() throws ServletException
    {
        super.init(); // maybe unnecessary

        /* Setup the DB connection */
        try {
            Properties dbProps = new Properties();
            dbProps.load(getClass().getResourceAsStream("database.properties"));

            Class.forName(dbProps.getProperty(dbPropertiesDriverClass));
            db = DriverManager.getConnection(dbProps.getProperty(dbPropertiesConnectionString));

            Properties configProps = new Properties();
            configProps.load(getClass().getResourceAsStream("projectservlet.properties"));

            googleAnalyticsCode = configProps.getProperty(configPropertiesGoogleAnalyticsCode, "");
            urlPathParam = configProps.getProperty(configPropertiesUrlPathParam, "up");

        } catch (IOException ex) {
            Logger.getLogger(DataServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new UnavailableException("Unable to initialize database connection");
        } catch (ClassNotFoundException ex) {
            Logger.getLogger(DataServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new UnavailableException("Unable to initialize database connection");
        } catch (SQLException ex) {
            Logger.getLogger(DataServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            throw new UnavailableException("Unable to initialize database connection");
        }
    }

    public void destroy()
    {
        super.destroy(); // maybe unnecessary

        /* Release database resources */
        try {
            db.rollback();
            db.close();
        } catch (SQLException ex) {
            Logger.getLogger(DataServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
        }
    }
    
    protected void doGet(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse) throws ServletException, IOException
    {        
        httpServletResponse.setContentType("text/html");

        /* First extract urlPath (by our convention it has not slashes)
         * from the request's path, then check whether this urlPath is
         * associated with any projects.
         */
        String urlPath;
        //urlPath = convertPathInfoToUrlPath(httpServletRequest.getPathInfo());
        //urlPath = httpServletRequest.getParameter("up");
        urlPath = httpServletRequest.getParameter(urlPathParam);
        //urlPath = httpServletRequest.getQueryString();

        int projectId;
        projectId = findProjectIdFromUrlPath(urlPath, httpServletResponse);  // pass in response for sending HTTP errors

        if ( projectId < 0 ) {
            httpServletResponse.sendError(HttpServletResponse.SC_NOT_FOUND, "No project registered for: " + urlPath);
        }

        generateProjectHostPage(projectId, httpServletResponse.getWriter(), true);
    }

    protected String convertPathInfoToUrlPath(String pathInfo)
    {
        if ( pathInfo.length() == 0 )
            return pathInfo;

        /* Remove trailing slash */
        if ( pathInfo.lastIndexOf("/") == (pathInfo.length() - 1 ) )
            pathInfo = pathInfo.substring(0, pathInfo.length() - 1);

        /* Remove starting slash */
        if ( pathInfo.indexOf("/") == 0 ) {
            if ( pathInfo.length() == 1 )
                pathInfo = "";
            else
                pathInfo = pathInfo.substring(1, pathInfo.length());
        }

        return pathInfo;
    }

    protected void generateProjectHostPage(int projectId, PrintWriter output, boolean closeOutput)
    {
        String scriptSrc;
        scriptSrc = "org.macdadi.ks.SingleProject/org.macdadi.ks.SingleProject.nocache.js";

        output.write("<html>\n");
	    output.write("  <head>\n");
        output.write("    <title>Welcome to MACDADI</title>\n");
        output.write("    <script type=\"text/javascript\">\n");
        output.write("      var project = { id: '" + projectId + "' };\n");
        output.write("    </script>\n");
        output.write("  </head>\n");
        output.write("  <body>\n");
        output.write("    <script language='javascript' src='" + scriptSrc + "'></script>\n");
        output.write("    <iframe src=\"javascript:''\" id=\"__gwt_historyFrame\" style=\"width:0;height:0;border:0\"></iframe>\n");
        /* Add Google Analytics Script tags */
        if ( ! googleAnalyticsCode.isEmpty() ) {
            output.write("    <script type=\"text/javascript\">\n");
            output.write("      var gaJsHost = ((\"https:\" == document.location.protocol) ? \"https://ssl.\" : \"http://www.\");\n");
            output.write("      document.write(unescape(\"%3Cscript src='\" + gaJsHost + \"google-analytics.com/ga.js' type='text/javascript'%3E%3C/script%3E\"));\n");
            output.write("    </script>\n");
            output.write("    <script type=\"text/javascript\">\n");
            output.write("      var pageTracker = _gat._getTracker(\"");
            output.write(googleAnalyticsCode);
            output.write("\");\n");
            output.write("      pageTracker._initData();\n");
            output.write("      pageTracker._trackPageview();\n");
            output.write("    </script>\n");
        }
        output.write("  </body>\n");
        output.write("</html> \n");

        if (closeOutput)
            output.close();
    }

    protected int findProjectIdFromUrlPath(String urlPath, HttpServletResponse response) throws IOException
    {
        int projectId = -1;

        try {
            String q = "SELECT id FROM projects WHERE url_path = ? ORDER BY id";
            // TODO: when projects have an is_active flag, exclude de-activated ones here

            PreparedStatement s = db.prepareStatement(q, ResultSet.TYPE_FORWARD_ONLY, ResultSet.CONCUR_READ_ONLY);
            s.setString(1, urlPath);

            ResultSet r = s.executeQuery();
            if (r.next()) {
                projectId = r.getInt(1);
            }
            s.close();
        } catch (SQLException ex) {
            Logger.getLogger(DataServiceImpl.class.getName()).log(Level.SEVERE, null, ex);
            response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR, "A database error occurred while looking up the specified project");
        }

        return projectId;
    }
}
